/**
 * @class ExtMVC.Model.Cache
 * @extends Ext.util.Observable
 * Provides an interface for caching model objects which have been fetched from some database/backend
 */
ExtMVC.Model.Cache = function(config) {
	var config = config || {};

	ExtMVC.Model.Cache.superclass.constructor.call(this, config);

	this.addEvents(
			/**
	 * @event beforeadd
	 * Fires before an item is added to the cache
	 * @param {ExtMVC.Model} modelObject The model which is about to be added
	 */
			'beforeadd',

			/**
			 * @event add
			 * Fires after an item is added to the cache
			 * @param {ExtMVC.Model} modelObject The model which was just added
			 */
			'add',

			/**
			 * @event beforeclear
			 * Fires before the cache is cleared
			 * @param {Number} seconds The number of seconds worth of caches which will be saved
			 */
			'beforeclear',

			/**
			 * @event clear
			 * Fires after the cache has been cleared
			 * @param {Number} seconds The number of seconds worth of caches which were saved
			 */
			'clear'
	);
};

Ext.extend(ExtMVC.Model.Cache, Ext.util.Observable, {

	/**
	 * @property caches
	 * @type Object
	 * Maintains all cached objects
	 */
	caches	: {},

	/**
	 * Adds the given model object to the cache.  Automatically stores the datetime of the add
	 * @param {ExtMVC.Model} modelObject The model you want to store in the cache
	 */
	add		: function(modelObject) {
		if (this.fireEvent('beforeadd', modelObject)) {
			var modelName = modelObject.className;
			var modelId = modelObject.data.id;

			if (modelName && modelId) {
				modelObject.cachedAt = new Date();

				this.caches[modelName] = this.caches[modelName] || {};
				this.caches[modelName][modelId] = modelObject;

				this.fireEvent('add', modelObject);
				return true;
			} else {

				return false;
			};
		}
	},

	/**
	 * Fetches an object from the cache
	 * @param {Object} params params object which must contain at least modelName and id.  Optionally 
	 * supply staleTime, which is the number of seconds old the cached object is allowed to be to get a hit,
	 * or a Date which will restrict hits to anything cached after that date
	 * @return {ExtMVC.Model/null} The model if found, or null
	 */
	fetch	: function(params) {
		this.caches[params['modelName']] = this.caches[params['modelName']]
				|| {};

		var params = params || {};
		var hit = this.caches[params['modelName']][params['id']];

		if (hit) {
			if (params.staleTime) {
				if (typeof params.staleTime == 'number') {
					var date = new Date();
					date.setTime(date.getTime() - (1000 * params.staleTime));
					params.staleTime = date;
				};

				// make sure we have a date object
				if (params.staleTime.getTime && hit.cachedAt > params.staleTime) {
					return hit;
				}
			} else {
				return hit;
			};
		};
	},

	/**
	 * Clears all objects more than the given number of seconds old (defaults to clearing all objects)
	 * @param {Number} seconds The number of seconds to keep cached objects for (e.g. setting this to 10 would delete anything cached more than 10 seconds ago)
	 */
	clear	: function(seconds) {
		var seconds = seconds || 0;
		var date = new Date();
		date.setTime(date.getTime() - (1000 * seconds));

		if (this.fireEvent('beforeclear', seconds)) {
			if (seconds == 0) {
				this.caches = {};
			} else {
				for (var i = 0; i < this.caches.length; i++) {
					for (var j = 0; j < this.caches[i].length; j++) {
						if (this.caches[i][j].cachedAt < date) {
							delete this.caches[i][j];
						};
					};
				};
			};

			this.fireEvent('clear', seconds);
		}
	}
}
);
